﻿using System;
using Xenta.Utils;

namespace Xenta.Structs
{
    /// <summary>
    /// Represents the search term.
    /// </summary>
    /// <remarks>
    /// The structure is used to define the search term.
    /// '%' character is used as a wildcard. The wildcard character
    /// may be used as a trailing and/or lead character.
    /// </remarks>
    public struct SearchTerm
    {
        #region Constants

        /// <summary>
        /// Wildcard characted.
        /// </summary>
        public const char WILDCARD_CHAR = '%';
        private const string WILDCARD_CHAR_STR = "%";

        /// <summary>
        /// Max keyword length.
        /// </summary>
        public const int KEYWORD_LEN_MAX = 100;

        /// <summary>
        /// Min keyword length(used only for the Contains mode search).
        /// </summary>
        public const int KEYWORD_LEN_MIN = 3;

        #endregion

        #region Fields

        private string _expression;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the search term expressions.
        /// </summary>
        public string Expression
        {
            get
            {
                return StringHelper.EnsureNotNull(_expression);
            }
            set
            {
                _expression = String.IsNullOrWhiteSpace(value) ? String.Empty : value.Trim();
            }
        }

        /// <summary>
        /// Gets the keyword.
        /// </summary>
        public string Keyword
        {
            get
            {
                return Expression.Trim(WILDCARD_CHAR).TrimToLen(KEYWORD_LEN_MAX);
            }
        }

        /// <summary>
        /// Gets or sets the component version.
        /// </summary>
        public SearchMode Mode
        {
            get
            {
                string keyword = Keyword;
                if(String.IsNullOrWhiteSpace(keyword))
                    return SearchMode.Skip;
                bool startWildcard = Expression.StartsWith(WILDCARD_CHAR_STR);
                bool endWildcard = Expression.EndsWith(WILDCARD_CHAR_STR);

                if(startWildcard && endWildcard)
                    if(keyword.Length < KEYWORD_LEN_MIN)
                        return SearchMode.Skip;
                    else
                        return SearchMode.Contains;
                else if(startWildcard)
                    return SearchMode.EndsWith;
                else if(endWildcard)
                    return SearchMode.StartsWith;
                else
                    return SearchMode.Equals;
            }
        }

        #endregion

        #region Enums

        /// <summary>
        /// Defines the search mode.
        /// </summary>
        public enum SearchMode
        {
            /// <summary>
            /// Skip this term.
            /// </summary>
            Skip,

            /// <summary>
            /// Search in the beginning.
            /// </summary>
            StartsWith,

            /// <summary>
            /// Search in the end.
            /// </summary>
            EndsWith,

            /// <summary>
            /// Search anywhere.
            /// </summary>
            Contains,

            /// <summary>
            /// Search for equality.
            /// </summary>
            Equals
        }

        #endregion

        #region Static

        /// <summary>
        /// Gets the empty search term.
        /// </summary>
        public static SearchTerm Empty
        {
            get
            {
                return new SearchTerm
                {
                    Expression = String.Empty
                };
            }
        }

        #endregion
    }
}
